<!--
 * Tencent is pleased to support the open source community by making BK-JOB蓝鲸智云作业平台 available.
 *
 * Copyright (C) 2021 THL A29 Limited, a Tencent company.  All rights reserved.
 *
 * BK-JOB蓝鲸智云作业平台 is licensed under the MIT License.
 *
 * License for BK-JOB蓝鲸智云作业平台:
 *
 *
 * Terms of the MIT License:
 * ---------------------------------------------------
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
 * documentation files (the "Software"), to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
 * to permit persons to whom the Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies or substantial portions of
 * the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
 * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
-->

<template>
	<layout class="template-list-page">
		<template #tag>
			<tag-panel ref="tagPanelRef" @on-change="handleTagPlanChange" />
		</template>
		<list-action-layout>
			<auth-button
				v-test="{ type: 'button', value: 'templateCreate' }"
				auth="job_template/create"
				class="w120 mr10"
				theme="primary"
				@click="handleCreate"
			>
				{{ $t('template.新建') }}
			</auth-button>
			<bk-badge
				class="mr10"
				theme="#006C45"
				:val="backupInfo.importJob.length"
				:visible="backupInfo.importJob.length > 0"
			>
				<span
					:tippy-tips="
						backupInfo.importJob.length > 0 ? $t('template.有一项导入任务正在进行中') : ''
					"
				>
					<auth-button
						v-test="{ type: 'button', value: 'templateImport' }"
						auth="job_template/create"
						@click="handleImport"
					>
						{{ $t('template.导入') }}
					</auth-button>
				</span>
			</bk-badge>
			<bk-badge
				class="mr10"
				theme="#006C45"
				:val="backupInfo.exportJob.length"
				:visible="backupInfo.exportJob.length > 0"
			>
				<span
					:tippy-tips="
						backupInfo.exportJob.length > 0 ? $t('template.有一项导出任务正在进行中') : ''
					"
				>
					<bk-button
						v-test="{ type: 'button', value: 'templateExport' }"
						:disabled="isExportJobDisable"
						@click="handleExport"
					>
						{{ $t('template.导出') }}
					</bk-button>
				</span>
			</bk-badge>
			<bk-button
				v-test="{ type: 'button', value: 'templateTagEdit' }"
				:disabled="isBatchEditTagDisabled"
				@click="handleBatchEditTag"
			>
				{{ $t('template.编辑标签') }}
			</bk-button>
			<template #right>
				<jb-search-select
					ref="search"
					:append-value="searchValue"
					:data="searchData"
					:placeholder="$t('template.输入 作业模板名、标签名 或 更新人 进行搜索...')"
					style="width: 420px"
					@on-change="handleSearch"
				/>
				<bk-button @click="handleMyTask">
					{{ $t('template.我的作业') }}
				</bk-button>
			</template>
		</list-action-layout>
		<div class="task-list-wraper">
			<render-list
				ref="list"
				v-test="{ type: 'list', value: 'template' }"
				:data-source="listDataSource"
				:search-control="() => $refs.search"
				selectable
				:size="tableSize"
				@on-selection-change="handleSelection"
			>
				<bk-table-column
					v-if="allRenderColumnMap.id"
					key="id"
					align="left"
					label="ID"
					prop="id"
					width="120"
				/>
				<bk-table-column
					v-if="allRenderColumnMap.name"
					key="name"
					align="left"
					class-name="task-name-column"
					:label="$t('template.作业模板名称')"
					min-width="300"
					prop="name"
				>
					<template slot-scope="{ row }">
						<auth-component
							auth="job_template/view"
							:permission="row.canView"
							:resource-id="row.id"
						>
							<div class="task-name-box">
								<icon
									class="task-collection"
									:class="row.favored ? 'favored' : 'unfavored'"
									type="collection"
									@click="handleCollection(row)"
								/>
								<router-link
									v-bk-overflow-tips
									class="task-name-text"
									:to="{
										name: 'templateDetail',
										params: {
											id: row.id,
										},
									}"
								>
									{{ row.name }}
								</router-link>
								<router-link
									:to="{
										name: 'templateDetail',
										params: {
											id: row.id,
										},
										query: {
											mode: 'scriptUpdate',
										},
									}"
								>
									<span v-html="row.scriptStatusHtml" />
								</router-link>
							</div>
							<div slot="forbid" class="task-name-box">
								<icon
									class="task-collection"
									:class="row.favored ? 'favored' : 'unfavored'"
									type="collection"
								/>
								<span v-bk-overflow-tips class="task-name-text">
									{{ row.name }}
								</span>
								<span>
									<span v-html="row.scriptStatusHtml" />
								</span>
							</div>
						</auth-component>
					</template>
				</bk-table-column>
				<bk-table-column
					v-if="allRenderColumnMap.tags"
					key="tags"
					align="left"
					class-name="edit-tag-column"
					:label="$t('template.场景标签.colHead')"
					prop="tags"
					width="200"
				>
					<template slot-scope="{ row }">
						<auth-component
							auth="job_template/edit"
							:permission="row.canEdit"
							:resource-id="row.id"
						>
							<jb-edit-tag
								:key="row.id"
								field="tags"
								:remote-hander="val => handleUpdateTask(row, val)"
								shortcurt
								:value="row.tags"
							/>
							<div slot="forbid">
								{{ row.tagText }}
							</div>
						</auth-component>
					</template>
				</bk-table-column>
				<bk-table-column
					v-if="allRenderColumnMap.statusText"
					key="statusText"
					align="left"
					:label="$t('template.状态')"
					prop="statusText"
					width="100"
				/>
				<bk-table-column
					v-if="allRenderColumnMap.creator"
					key="creator"
					align="left"
					:label="$t('template.创建人')"
					prop="creator"
					width="120"
				/>
				<bk-table-column
					v-if="allRenderColumnMap.createTime"
					key="createTime"
					align="left"
					:label="$t('template.创建时间')"
					prop="createTime"
					width="180"
				/>
				<bk-table-column
					v-if="allRenderColumnMap.lastModifyUser"
					key="lastModifyUser"
					align="left"
					:label="$t('template.更新人.colHead')"
					prop="lastModifyUser"
					width="160"
				/>
				<bk-table-column
					v-if="allRenderColumnMap.lastModifyTime"
					key="lastModifyTime"
					align="left"
					:label="$t('template.更新时间')"
					prop="lastModifyTime"
					width="180"
				/>
				<bk-table-column
					key="action"
					fixed="right"
					:label="$t('template.操作')"
					:resizable="false"
					width="130"
				>
					<template slot-scope="{ row }">
						<router-link
							v-test="{ type: 'link', value: 'planDetail' }"
							class="mr10"
							:to="{
								name: 'viewPlan',
								params: { templateId: row.id },
							}"
						>
							{{ $t('template.执行方案.label') }}
						</router-link>
						<router-link
							v-test="{ type: 'link', value: 'debugTemplate' }"
							class="mr10"
							:to="{
								name: 'debugPlan',
								params: { id: row.id },
								query: { from: 'taskList' },
							}"
						>
							{{ $t('template.调试') }}
						</router-link>
						<list-operation-extend>
							<auth-component
								auth="job_template/edit"
								:permission="row.canEdit"
								:resource-id="row.id"
							>
								<div
									v-test="{ type: 'button', value: 'editTemplate' }"
									class="action-item"
									@click="handleEdit(row.id)"
								>
									{{ $t('template.编辑') }}
								</div>
								<div
									slot="forbid"
									v-test="{ type: 'button', value: 'editTemplate' }"
									class="action-item"
								>
									{{ $t('template.编辑') }}
								</div>
							</auth-component>
							<auth-component
								auth="job_template/clone"
								:permission="row.canCreate && row.canView"
								:resource-id="row.id"
							>
								<div
									v-test="{ type: 'button', value: 'cloneTemplate' }"
									class="action-item"
									@click="handleClone(row.id)"
								>
									{{ $t('template.克隆') }}
								</div>
								<div
									slot="forbid"
									v-test="{ type: 'button', value: 'cloneTemplate' }"
									class="action-item"
								>
									{{ $t('template.克隆') }}
								</div>
							</auth-component>
							<jb-popover-confirm
								:confirm-handler="() => handleDelete(row.id)"
								:content="$t('template.注意！模板下关联的所有执行方案也将被清除')"
								:title="$t('template.确定删除该作业？')"
							>
								<auth-component
									auth="job_template/delete"
									:permission="row.canDelete"
									:resource-id="row.id"
								>
									<div v-test="{ type: 'button', value: 'deleteTemplate' }" class="action-item">
										{{ $t('template.删除') }}
									</div>
									<div
										slot="forbid"
										v-test="{ type: 'button', value: 'deleteTemplate' }"
										class="action-item"
									>
										{{ $t('template.删除') }}
									</div>
								</auth-component>
							</jb-popover-confirm>
						</list-operation-extend>
					</template>
				</bk-table-column>
				<bk-table-column type="setting">
					<bk-table-setting-content
						:fields="tableColumn"
						:selected="selectedTableColumn"
						:size="tableSize"
						@setting-change="handleSettingChange"
					/>
				</bk-table-column>
			</render-list>
		</div>
		<jb-dialog
			v-model="isShowBatchEdit"
			header-position="left"
			:ok-text="$t('template.确定')"
			:title="$t('template.编辑标签')"
			:width="480"
		>
			<batch-edit-tag
				v-if="isShowBatchEdit"
				:template-list="listSelect"
				@on-change="handleBatchEditChange"
			/>
		</jb-dialog>
	</layout>
</template>
<script>
import BackupService from '@service/backup';
import NotifyService from '@service/notify';
import TagManageService from '@service/tag-manage';
import TaskService from '@service/task-manage';
import UserService from '@service/user';

import { listColumnsCache, taskExport } from '@utils/cache-helper';

import JbEditTag from '@components/jb-edit/tag';
import JbPopoverConfirm from '@components/jb-popover-confirm';
import JbSearchSelect from '@components/jb-search-select';
import ListActionLayout from '@components/list-action-layout';
import ListOperationExtend from '@components/list-operation-extend';
import RenderList from '@components/render-list';

import I18n from '@/i18n';

import BatchEditTag from './components/batch-edit-tag.vue';
import Layout from './components/layout';
import TagPanel from './components/tag-panel';

const TABLE_COLUMN_CACHE = 'task_list_columns';

export default {
	name: 'TaskManageList',
	components: {
		JbEditTag,
		ListActionLayout,
		RenderList,
		ListOperationExtend,
		JbSearchSelect,
		JbPopoverConfirm,
		Layout,
		TagPanel,
		BatchEditTag,
	},
	data() {
		return {
			isShowBatchEdit: false,
			currentUser: {},
			searchValue: [],
			listSelect: [],
			backupInfo: {
				importJob: [],
				exportJob: [],
			},
			selectedTableColumn: [],
			tableSize: 'small',
		};
	},
	computed: {
		/**
		 * @desc 列表骨架屏 loading
		 * @returns { Boolean }
		 */
		isSkeletonLoading() {
			return this.$refs.list.isLoading;
		},
		/**
		 * @desc 导出功能禁用
		 * @returns { Boolean }
		 *
		 * 1，有导入任务未完成，继续上一次的任务
		 * 2，未选中作业
		 * 3，选中的作业没用查看权限
		 */
		isExportJobDisable() {
			if (this.backupInfo.exportJob.length > 0) {
				return false;
			}
			// eslint-disable-next-line no-plusplus
			for (let i = 0; i < this.listSelect.length; i++) {
				const current = this.listSelect[i];
				if (!current.canView) {
					return true;
				}
			}
			return this.listSelect.length < 1;
		},
		/**
		 * @desc 导出功能禁用
		 * @returns { Boolean }
		 *
		 * 1，未选中作业
		 * 2，选中的作业没用查看权限
		 */
		isBatchEditTagDisabled() {
			// eslint-disable-next-line no-plusplus
			for (let i = 0; i < this.listSelect.length; i++) {
				const current = this.listSelect[i];
				if (!current.canEdit) {
					return true;
				}
			}
			return this.listSelect.length < 1;
		},
		allRenderColumnMap() {
			return this.selectedTableColumn.reduce((result, item) => {
				result[item.id] = true;
				return result;
			}, {});
		},
	},
	created() {
		this.searchParams = {};
		this.searchClass = {};
		this.listDataSource = TaskService.taskList;
		this.searchData = [
			{
				name: 'ID',
				id: 'templateId',
				description: I18n.t('template.将覆盖其它条件'),
				validate(values, item) {
					const validate = (values || []).every(_ => /^(\d*)$/.test(_.name));
					return !validate ? I18n.t('template.ID只支持数字') : true;
				},
			},
			{
				name: I18n.t('template.作业模板名称'),
				id: 'name',
				default: true,
			},
			{
				name: I18n.t('template.场景标签.colHead'),
				id: 'tags',
				remoteMethod: TagManageService.fetchTagOfSearch,
			},
			{
				name: I18n.t('template.更新人.colHead'),
				id: 'lastModifyUser',
				remoteMethod: NotifyService.fetchUsersOfSearch,
				inputInclude: true,
			},
			{
				name: I18n.t('template.创建人'),
				id: 'creator',
				remoteMethod: NotifyService.fetchUsersOfSearch,
				inputInclude: true,
			},
		];
		this.tableColumn = [
			{
				id: 'id',
				label: 'ID',
			},
			{
				id: 'name',
				label: I18n.t('template.作业模板名称'),
				disabled: true,
			},
			{
				id: 'tags',
				label: I18n.t('template.场景标签.colHead'),
			},
			{
				id: 'statusText',
				label: I18n.t('template.状态'),
			},
			{
				id: 'creator',
				label: I18n.t('template.创建人'),
			},
			{
				id: 'createTime',
				label: I18n.t('template.创建时间'),
			},
			{
				id: 'lastModifyUser',
				label: I18n.t('template.更新人.colHead'),
			},
			{
				id: 'lastModifyTime',
				label: I18n.t('template.更新时间'),
			},
		];
		const columnsCache = listColumnsCache.getItem(TABLE_COLUMN_CACHE);
		if (columnsCache) {
			this.selectedTableColumn = Object.freeze(columnsCache.columns);
			this.tableSize = columnsCache.size;
		} else {
			this.selectedTableColumn = Object.freeze([
				{ id: 'name' },
				{ id: 'tags' },
				{ id: 'lastModifyUser' },
				{ id: 'lastModifyTime' },
			]);
		}
	},
	mounted() {
		this.fetchUserInfo();
		this.fetchBackup();
	},
	methods: {
		/**
		 * @desc 获取作业模板列表
		 */
		fetchData() {
			// 合并左侧分类和右侧搜索的查询条件
			const searchParams = { ...this.searchParams };
			if (this.searchClass.type) {
				searchParams.type = this.searchClass.type;
			}
			if (this.searchClass.panelTag) {
				searchParams.panelTag = this.searchClass.panelTag;
			}
			this.$refs.list.$emit('onFetch', searchParams);
		},
		/**
		 * @desc 获取登录用户名
		 */
		fetchUserInfo() {
			UserService.fetchUserInfo().then(data => {
				this.currentUser = data;
			});
		},
		/**
		 * @desc 获取作业模板导出记录信息
		 */
		fetchBackup() {
			BackupService.fetchInfo().then(data => {
				this.backupInfo = Object.freeze(data);
			});
		},
		/**
		 * @desc 列表自定义配置
		 */
		handleSettingChange({ fields, size }) {
			this.selectedTableColumn = Object.freeze(fields);
			this.tableSize = size;
			listColumnsCache.setItem(TABLE_COLUMN_CACHE, {
				columns: fields,
				size,
			});
		},
		/**
		 * @desc 切换分类
		 * @param {String} searchClass 最新分类
		 */
		handleTagPlanChange(searchClass) {
			this.searchClass = searchClass;
			this.fetchData();
		},
		/**
		 * @desc 切换分类
		 * @param {Object} params 搜索参数
		 */
		handleSearch(params) {
			this.searchParams = params;
			this.fetchData();
		},
		/**
		 * @desc 跳转作业模板新建页
		 */
		handleCreate() {
			this.$router.push({
				name: 'templateCreate',
				query: {
					from: 'list',
				},
			});
		},
		/**
		 * @desc 跳转作业模板导入页
		 */
		handleImport() {
			this.$router.push({
				name: 'taskImport',
			});
		},
		/**
		 * @desc 导出选中的作业模板
		 *
		 * 同时只能存在一个导出任务，如果有导出任务没有结束给出提示
		 */
		handleExport() {
			const confirmFn = () => {
				this.$router.push({
					name: 'taskExport',
				});
				taskExport.setItem(
					'ids',
					this.listSelect.map(_ => _.id)
				);
			};
			if (this.backupInfo.exportJob.length > 0 && this.listSelect.length > 0) {
				this.$bkInfo({
					title: I18n.t('template.上一次任务还未完成'),
					subTitle: I18n.t('template.您上一次的任务还在后台运行中，请先等待完成后再发起新的任务。'),
					okText: I18n.t('template.查看'),
					cancelText: I18n.t('template.返回'),
					confirmFn,
				});
			} else {
				confirmFn();
			}
		},
		/**
		 * @desc 批量编辑 TAG
		 */
		handleBatchEditTag() {
			this.isShowBatchEdit = true;
		},
		/**
		 * @desc tag 批量编辑完成需要刷新列表和 tag 面板数据
		 */
		handleBatchEditChange() {
			this.fetchData();
			this.$refs.tagPanelRef.init();
		},
		/**
		 * @desc 查看登录用户的作业模板
		 */
		handleMyTask() {
			const currentUserName = this.currentUser.username;
			const creator = {
				name: I18n.t('template.创建人'),
				id: 'creator',
				values: [
					{
						id: currentUserName,
						name: currentUserName,
					},
				],
			};
			this.searchParams = {
				...this.searchParams,
				creator: currentUserName,
			};
			this.searchValue = [creator];
			this.fetchData();
		},
		/**
		 * @desc 更新作业模板基本信息
		 * @param {Object} task 作业模板数据
		 * @param {Object} payload 编辑的数据
		 */
		handleUpdateTask(task, payload) {
			const { id, name, description } = task;
			return TaskService.taskUpdateBasic({
				id,
				name,
				description,
				tags: payload.tags,
			}).then(() => {
				this.$refs.tagPanelRef.init();
			});
		},
		/**
		 * @desc 选择作业模板
		 * @param {Array} selectTemplate 选择的作业模板
		 */
		handleSelection(selectTemplate) {
			this.listSelect = Object.freeze(selectTemplate);
		},
		/**
		 * @desc 编辑作业模板
		 * @param {Number} id 选中的作业模板
		 */
		handleEdit(id) {
			this.$router.push({
				name: 'templateEdit',
				params: { id },
				query: {
					from: 'list',
				},
			});
		},
		/**
		 * @desc 克隆作业模板
		 * @param {Number} id 选中的作业模板
		 */
		handleClone(id) {
			this.$router.push({
				name: 'templateClone',
				params: { id },
				query: {
					from: 'list',
				},
			});
		},
		/**
		 * @desc 删除作业模板
		 * @param {Number} id 选中的作业模板
		 */
		handleDelete(id) {
			return TaskService.taskDelete({
				id,
			}).then(() => {
				this.fetchData();
				this.messageSuccess(I18n.t('template.删除模板成功'));
				this.$refs.tagPanelRef.init();
				return true;
			});
		},
		/**
		 * @desc 收藏作业模板
		 * @param {Object} task 选中的作业模板
		 */
		handleCollection(task) {
			const requestHander = task.favored
				? TaskService.taskDeleteFavorite
				: TaskService.taskUpdateFavorite;
			requestHander({
				id: task.id,
			}).then(() => {
				task.toggleFavored();
				this.messageSuccess(
					task.favored ? I18n.t('template.收藏成功') : I18n.t('template.取消收藏成功')
				);
			});
		},
	},
};
</script>
<style lang="postcss">
.template-list-page {
	.bk-table tr:hover {
		td.task-name-column {
			.task-name-box {
				.task-collection {
					display: inline-block;
				}
			}
		}
	}

	td.task-name-column {
		.cell {
			margin-left: -22px;
		}

		.task-name-box {
			position: relative;
			padding-left: 22px;

			.task-collection {
				position: absolute;
				top: 50%;
				left: 0;
				font-size: 14px;
				color: #c4c6cc;
				cursor: pointer;
				transform: translateY(-50%);

				&.unfavored {
					display: none;
				}

				&.favored {
					display: inline-block;
					color: #ffd695;
				}
			}

			.task-name-text {
				display: inline-block;
				height: 18px;
				max-width: calc(100% - 22px);
				overflow: hidden;
				text-overflow: ellipsis;
				white-space: nowrap;
				vertical-align: bottom;
			}
		}
	}
}
</style>
